package com.lxs.mall.controller;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.lxs.mall.common.ApiRestResponse;
import com.lxs.mall.common.Constant;
import com.lxs.mall.exception.LxsMallException;
import com.lxs.mall.exception.LxsMallExceptionEnum;
import com.lxs.mall.filter.UserFilter;
import com.lxs.mall.model.pojo.User;
import com.lxs.mall.service.EmailService;
import com.lxs.mall.service.UserService;
import com.lxs.mall.util.EmailUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.concurrent.ExecutorService;

/**
 * 用戶控制器
 *
 * @author 小松
 */
@Controller
public class UserController {
    @Resource
    UserService userService;
    @Resource
    EmailService emailService;
    @Resource
    ExecutorService executorService;

    @ApiOperation("测试")
    @GetMapping("/test")
    @ResponseBody
    public User personPage() {
        return userService.getUser();
    }

    /**
     * 注册
     */
    @ApiOperation("注册")
    @PostMapping("/register")
    @ResponseBody
    public ApiRestResponse register(@RequestParam("username") String username,
                                    @RequestParam("password") String password,
                                    @RequestParam("emailAddress") String emailAddress,
                                    @RequestParam("verificationCode") String verificationCode
    ) throws LxsMallException {
        if (StringUtils.isEmpty(username)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_USER_NAME);
        }
        if (StringUtils.isEmpty(password)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_PASSWORD);
        }
        if (password.length() < 8) {
            return ApiRestResponse.error(LxsMallExceptionEnum.PASSWORD_TOO_SHORT);
        }
        if (StringUtils.isEmpty(emailAddress)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.EMAIL_NOT_NULL);
        }
        if (StringUtils.isEmpty(verificationCode)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.VERIFICATION_CODE_NOT_NULL);
        }
        //如果邮箱已注册则不允许重复注册
        boolean emailPassed = userService.checkEmailAddress(emailAddress);
        if (!emailPassed) {
            return ApiRestResponse.error(
                    LxsMallExceptionEnum.EMAIL_ADDRESS_BEEN_REGISTERED);
        }
        //验证验证码是否匹配
        Boolean passEmailCode = emailService.checkEmailCode(emailAddress, verificationCode);
        if (!passEmailCode) {
            return ApiRestResponse.error(LxsMallExceptionEnum.WRONG_VERIFICATION_CODE);
        }
        userService.register(username, password, emailAddress);
        return ApiRestResponse.success();
    }

    /**
     * 登录
     */
    @ApiOperation("用户登录")
    @PostMapping("/login")
    @ResponseBody
    public ApiRestResponse selectLogin(@RequestParam("username") String username,
                                       @RequestParam("password") String password,
                                       HttpSession httpSession) throws LxsMallException {
        if (StringUtils.isEmpty(username)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_USER_NAME);
        }
        if (StringUtils.isEmpty(password)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_PASSWORD);
        }
        User user = userService.login(username, password);
        user.setPassword(null);
        httpSession.setAttribute(Constant.LXS_MALL_USER, user);
        return ApiRestResponse.success(user);
    }

    /**
     * 更新个性签名
     */
    @ApiOperation("更新个性签名")
    @PostMapping("/user/update")
    @ResponseBody
    public ApiRestResponse updateUserInfo(HttpSession httpSession, @RequestParam String signature) throws LxsMallException {
        //User currentUser = (User) httpSession.getAttribute(Constant.LXS_MALL_USER);
        User currentUser = UserFilter.userThreadLocal.get();
        if (currentUser == null) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_LOGIN);
        }
        User user = new User();
        user.setId(currentUser.getId());
        user.setPersonalizedSignature(signature);
        userService.updateInformation(user);
        return ApiRestResponse.success();
    }

    /**
     * 登出，清楚session
     *
     * @param httpSession
     * @return
     */
    @ApiOperation("登出-清除session")
    @PostMapping("/user/logout")
    @ResponseBody
    public ApiRestResponse logout(HttpSession httpSession) {
        httpSession.removeAttribute(Constant.LXS_MALL_USER);
        return ApiRestResponse.success();
    }

    /**
     * 管理员登录
     *
     * @param username
     * @param password
     * @param httpSession
     * @return
     * @throws LxsMallException
     */
    @ApiOperation("管理员登录")
    @PostMapping("/adminLogin")
    @ResponseBody
    public ApiRestResponse adminLogin(@RequestParam("username") String username,
                                      @RequestParam("password") String password,
                                      HttpSession httpSession) throws LxsMallException {
        if (StringUtils.isEmpty(username)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_USER_NAME);
        }
        if (StringUtils.isEmpty(password)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_PASSWORD);
        }
        User user = userService.login(username, password);
        //检验是否为管理员
        if (userService.checkAdmin(user)) {
            //是管理员
            user.setPassword(null);
            httpSession.setAttribute(Constant.LXS_MALL_USER, user);
            return ApiRestResponse.success(user);
        } else {
            //不是管理员
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_ADMIN);
        }
    }

    @ApiOperation("发送邮件")
    @PostMapping("/user/sendEmail")
    @ResponseBody
    public ApiRestResponse sendEmail(@RequestParam String emailAddress) {
        //检查邮箱地址是否有效,检查是否已注册
        boolean valid = EmailUtil.isValidEmailAddress(emailAddress);
        if (valid) {
            boolean emailPassed = userService.checkEmailAddress(emailAddress);
            if (!emailPassed) {
                return ApiRestResponse.error(
                        LxsMallExceptionEnum.EMAIL_ADDRESS_BEEN_REGISTERED);
            } else {
                String verificationCode = EmailUtil.generateVerificationCode();
                Boolean saveEmailToRedis = emailService.saveEmailToRedis(emailAddress, verificationCode);
                if (saveEmailToRedis) {
                    //邮箱发送的线程优化的优化，没替换前需要发送完才返回成功，
                    // 加入线程池后现在只需要运行就能返回成功，不必要等到邮件发送了才返回成功（
                    // 可替换成lambda表达式简化）
                    executorService.submit(new Runnable() {
                        @Override
                        public void run() {
                            emailService.sendSimpleMessage(emailAddress, Constant.EMAIL_SUBJECT,
                                    "欢迎注册，您的验证码是" + verificationCode);
                        }
                    });
                    return ApiRestResponse.success();
                } else {
                    return ApiRestResponse.error(LxsMallExceptionEnum.EMAIL_ADDRESS_BEEN_SEND);
                }

            }
        } else {
            return ApiRestResponse.error(LxsMallExceptionEnum.WRONG_EMAIL);
        }
    }

    @ApiOperation("Jwt用户登录")
    @PostMapping("/loginWithJwt")
    @ResponseBody
    public ApiRestResponse loginWithJwt(@RequestParam("username") String username,
                                        @RequestParam("password") String password
    ) throws LxsMallException {
        if (StringUtils.isEmpty(username)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_USER_NAME);
        }
        if (StringUtils.isEmpty(password)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_PASSWORD);
        }
        User user = userService.login(username, password);
        user.setPassword(null);
        Algorithm algorithm = Algorithm.HMAC256(Constant.JWT_KEY);
        String token = JWT.create()
                .withClaim(Constant.USER_NAME, user.getUsername())
                .withClaim(Constant.USER_ID, user.getId())
                .withClaim(Constant.USER_ROLE, user.getRole())
                //过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + Constant.EXPIRE_TIME))
                .sign(algorithm);
        return ApiRestResponse.success(token);
    }

    @ApiOperation("Jwt管理员登录")
    @PostMapping("/adminLoginWithJwt")
    @ResponseBody
    public ApiRestResponse adminLoginWithJwt(@RequestParam("username") String username,
                                             @RequestParam("password") String password)
            throws LxsMallException {
        if (StringUtils.isEmpty(username)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_USER_NAME);
        }
        if (StringUtils.isEmpty(password)) {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_PASSWORD);
        }
        User user = userService.login(username, password);
        //校验是否是管理员
        if (userService.checkAdmin(user)) {
            //是管理员，执行操作
            //保存用户信息时，不保存密码
            user.setPassword(null);
            Algorithm algorithm = Algorithm.HMAC256(Constant.JWT_KEY);
            String token = JWT.create()
                    .withClaim(Constant.USER_NAME, user.getUsername())
                    .withClaim(Constant.USER_ID, user.getId())
                    .withClaim(Constant.USER_ROLE, user.getRole())
                    //过期时间
                    .withExpiresAt(new
                            Date(System.currentTimeMillis() + Constant.EXPIRE_TIME))
                    .sign(algorithm);
            return ApiRestResponse.success(token);
        } else {
            return ApiRestResponse.error(LxsMallExceptionEnum.NEED_ADMIN);
        }
    }
}
